package com.example.yk2021xm04.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.yk2021xm04.mapper.UserMapper;
import com.example.yk2021xm04.pojo.User;
import com.example.yk2021xm04.pojo.UserRole;
import com.example.yk2021xm04.query.UserQuery;
import com.example.yk2021xm04.service.IMailService;
import com.example.yk2021xm04.service.IUserRoleService;
import com.example.yk2021xm04.service.IUserService;
import com.example.yk2021xm04.utils.AssertUtil;
import com.example.yk2021xm04.utils.PageResultUtil;
import com.example.yk2021xm04.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author ZengQi
 * @since 2021-11-26
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private IMailService mailService;

    @Resource
    private IUserRoleService userRoleService;

//    @Override
//    public User login(String userName, String password) {
//        //判断用户名是否为空
//        AssertUtil.isTrue(StringUtil.isEmpty(userName),"用户名不能为空!");
//        //判断密码是否为空
//        AssertUtil.isTrue(StringUtil.isEmpty(password),"密码不能为空!");
//        User user = this.findUserByUserName(userName);
//        //能不能找到用户
//        AssertUtil.isTrue(null == user,"该用户记录不存在或已注销!");
//        System.out.println(user);
//        //然后就是账号密码正不正确
//        AssertUtil.isTrue(!(user.getPassword().equals(password)),"密码错误!");
//
//        AssertUtil.isTrue(user.getActiveStatus() == 0, "该用户未激活");
//        /**
//         * 后续引入SpringSecurity 使用框架处理密码
//         */
//        return user;
//    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void register(User user) {
        /**
         * 用户名
         * 不可重复
         * 用户默认有效
         * 设置默认备注和默认描述
         */
        User oldUser = this.findUserByUserName(user.getUsername());
        AssertUtil.isTrue(null != oldUser, "用户已存在");
        int roleId = user.getRoleId();
        String bz = "";
        String remarks = "";
        if(roleId==2) {
            bz="项目经理";
            remarks="产品经理，管理项目成员，管理项目";
        } else if(roleId==3) {
            bz="项目成员";
            remarks="项目普通成员，项目代码编写";
        } else if(roleId==4){
            bz="主管";
            remarks="项目总监，负责管理多个项目组";
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setBz(bz);
        user.setRemarks(remarks);
        user.setIsDel(0);
        user.setRegisterTime(LocalDateTime.now());
        System.out.println(user);
        AssertUtil.isTrue(!(this.save(user)),"用户记录添加失败");

        String code = user.getActiveCode();
        System.out.println("激活码:"+code);
        String subject = "来自项目管理系统的激活邮件";
        //上面的激活码发送到用户注册邮箱
        String context = "<a href=\"http://www.ylxteach.net/yk2021-xm04/user/checkCode?active_code="+code+"\">激活请点击:"+code+"</a>";
        //发送激活邮件
        mailService.sendMimeMail(user.getEmail(),subject,context);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addUser(User user) {
        /**
         * 用户名
         * 非空 不可重复
         * 默认密码为123
         * 用户默认有效
         */
        AssertUtil.isTrue(StringUtils.isBlank(user.getUsername()),"用户名不能为空");
        AssertUtil.isTrue(null!=this.findUserByUserName(user.getUsername()),"用户名已存在");
        user.setPassword(passwordEncoder.encode("123"));
        user.setIsDel(0);
        user.setActiveStatus(1);
        user.setRegisterTime(LocalDateTime.now());
        AssertUtil.isTrue(!(this.save(user)),"用户记录添加失败");

        //重新分配用户记录
        User temp = this.findUserByUserName(user.getUsername());
        /**
         * 分配角色
         */
        relationUserRole(temp.getId(), user.getRoleIds());
    }

    private void relationUserRole(Integer userId, String roleIds) {
        /**
         * 核心表  t_user_role
         *   添加时
         *     如果角色记录存在  执行批量添加即可
         *   更新时
         *     如果用户存在原始角色记录
         *         如果存在  直接删除原来用户角色记录即可 重新添加新的用户角色记录
         *
         *         如果不存在  直接执行添加即可
         *
         *
         * 实现思路
         *    首先查询用户原始分配角色
         *       如果存在原始用户角色记录  直接删除原来用户角色记录即可（根据用户id） 然后重新添加新的用户角色记录
         *       如果不存在
         *          直接执行批量添加即可
         */
        int count = userRoleService.count(new QueryWrapper<UserRole>().eq("user_id",userId));
        if (count > 0) {
            AssertUtil.isTrue(!(userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id",userId))),"用户角色分配失败");
        }
        System.out.println("该用户拥有角色数量："+count);
        System.out.println("该用户拥有角色id："+roleIds);
        if(StringUtils.isNotBlank(roleIds)) {
            List<UserRole> userRoles = new ArrayList<>();
            for (String s : roleIds.split(",")) {
                UserRole userRole =new UserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(Integer.parseInt(s));
                userRoles.add(userRole);
            }
            AssertUtil.isTrue(!(userRoleService.saveBatch(userRoles)),"用户角色分配失败");
        }
        System.out.println("用户角色分配成功");
    }

    @Override
    public Map<String, Object> userList(UserQuery userQuery) {
        //分页的类
        IPage<User> page = new Page<User>(userQuery.getPage(), userQuery.getLimit());
        //QueryWrapper：sql条件查询
        //eq("is_del", 0) 代表 where is_del=0
        //详细可搜索相关用法
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        queryWrapper.eq("is_del",0).eq("active_status",1);

        //这里就是代表 sql语句中的 like
        if(StringUtils.isNotBlank(userQuery.getUserName())) {
            queryWrapper.like("user_name",userQuery.getUserName());
        }
        //已经写好的接口
        page = this.baseMapper.selectPage(page,queryWrapper);
        return PageResultUtil.getResult(page.getTotal(),page.getRecords());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteUser(Integer[] ids) {
        /**
         * 批量删除用户
         */
        AssertUtil.isTrue(null==ids || ids.length==0,"请选择待删除的id");

        /**
         * 第一种删除，只设置IsDel值为1，不从数据库中删除
         */
//        List<User> users = new ArrayList<>();
//        for (Integer id : ids) {
//            User temp = this.getById(id);
//            temp.setIsDel(1);
//            users.add(temp);
//        }
//        AssertUtil.isTrue(!(this.updateBatchById(users)),"用户记录删除失败");
        /**
         * 第二种删除，直接从数据库删除
         * 先采用这一种
         */
        int count = userRoleService.count(new QueryWrapper<UserRole>().in("user_id",Arrays.asList(ids)));
        if (count > 0) {
            AssertUtil.isTrue(!(userRoleService.remove(new QueryWrapper<UserRole>().in("user_id",Arrays.asList(ids)))),
                    "用户记录删除失败");
        }
        AssertUtil.isTrue(!(this.removeByIds(Arrays.asList(ids))),"用户记录删除失败");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateUser(User user) {
        /**
         * 用户名
         * 非空 不可重复
         */
        AssertUtil.isTrue(StringUtils.isBlank(user.getUsername()),"用户名不能为空");
        User temp = this.findUserByUserName(user.getUsername());
        AssertUtil.isTrue(null!=temp&&!(temp.getId().equals(user.getId())),"用户名已存在！");
        System.out.println(user);
        if(user.getRoleIds() == null) {
            /**
             * 用户初始激活时根据RoleId分配角色
             */
            String roleIds = String.valueOf(user.getRoleId());
            user.setRoleIds(roleIds);
            relationUserRole(user.getId(), roleIds);
        }
        relationUserRole(user.getId(),user.getRoleIds());

        AssertUtil.isTrue(!(this.updateById(user)),"用户记录更新失败");
    }

    @Override
    public User getUserByActiveCode(String active_code) {
        return this.baseMapper.selectOne(new QueryWrapper<User>().eq("active_code",active_code));
    }

    @Override
    public User findUserByProjectLeader(String projectLeader) {
        return this.baseMapper.selectOne(new QueryWrapper<User>().eq("true_name",projectLeader));
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateUserInfo(User user) {
        /**
         * 用户名
         *    非空
         *    唯一
         */
        AssertUtil.isTrue(StringUtil.isEmpty(user.getUsername()),"用户名不能为空!");
        User temp = this.findUserByUserName(user.getUsername());
        AssertUtil.isTrue(null !=temp && !(temp.getId().equals(user.getId())),"用户名已存在!");
        AssertUtil.isTrue(!(this.updateById(user)),"用户信息更新失败!");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateUserPassword(String userName, String oldPassword, String newPassword, String confirmPassword) {
        /**
         * 用户名非空 必须存在
         * 原始密码 新密码 确认密码 不能为空
         * 原始密码必须正确
         * 新密码 与 确认密码 必须一致 并且不能与原始密码相同
         */
        User user = null;
        user = this.findUserByUserName(userName);
        AssertUtil.isTrue(null==user,"用户不存在或未登录");
        AssertUtil.isTrue(StringUtil.isEmpty(oldPassword), "请输入原始密码");
        AssertUtil.isTrue(StringUtil.isEmpty(newPassword), "请输入新密码");
        AssertUtil.isTrue(StringUtil.isEmpty(confirmPassword), "请输入确认密码");
        AssertUtil.isTrue(!(passwordEncoder.matches(oldPassword, user.getPassword())), "原始密码输入错误");
        AssertUtil.isTrue(!(newPassword.equals(confirmPassword)), "新密码与确认密码输入不一致");
        AssertUtil.isTrue(newPassword.equals(oldPassword), "新密码不能与原始密码相同");
        user.setPassword(passwordEncoder.encode(newPassword));
        AssertUtil.isTrue(!(this.updateById(user)), "用户密码更新失败");
    }

    @Override
    public List<Object> registerTimeByDay() {
        return this.baseMapper.registerTimeByDay();
    }

    @Override
    public List<Object> registerCountByDay() {
        return this.baseMapper.registerCountByDay();
    }

    @Override
    public Integer UserCountInDay() {
        return this.baseMapper.UserCountInDay();
    }

    @Override
    public Integer UserCountInYesterday() {
        return this.baseMapper.UserCountInYesterday();
    }

    @Override
    public User findUserByUserName(String userName) {
        return this.baseMapper.selectOne(new QueryWrapper<User>().eq("is_del",0).eq("user_name",userName));
    }
}
